package com.xbongbong.pro.statistic.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.bi.pojo.DataSetNodeFieldPojo;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.BIProductReformEnum;
import com.xbongbong.paas.enums.DateDiffTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.ScreenTypeEnum;
import com.xbongbong.paas.enums.bi.ConfigExecuteRateEnum;
import com.xbongbong.paas.enums.bi.ConfigTypeEnum;
import com.xbongbong.paas.enums.bi.DataSetFieldBgColorEnum;
import com.xbongbong.paas.enums.bi.DataSetFieldStatusEnum;
import com.xbongbong.paas.enums.bi.DataSetJoinEnum;
import com.xbongbong.paas.enums.bi.DataSetOperateEnum;
import com.xbongbong.paas.enums.bi.DataSetPermissionEnum;
import com.xbongbong.paas.enums.bi.DataSetStatusEnum;
import com.xbongbong.paas.enums.bi.DataSetTitleEnum;
import com.xbongbong.paas.enums.bi.XbbTableRefEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.field.VisibleRulePoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.pojo.BiExplainPojo;
import com.xbongbong.paas.pojo.DsAttrValuePojo;
import com.xbongbong.paas.pojo.KeyAndValuePojo;
import com.xbongbong.paas.pojo.KeyValuePojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.domain.entity.DataSetConfigEntity;
import com.xbongbong.pro.domain.entity.DataSetEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.pojo.DataSetLogInfoPojo;
import com.xbongbong.pro.statistic.constant.DataSetConstant;
import com.xbongbong.pro.statistic.constant.RelatedProductConstant;
import com.xbongbong.pro.statistic.enums.ChartAttrTypeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.help.ChartAttrHelp;
import com.xbongbong.pro.statistic.help.CustomHelp;
import com.xbongbong.pro.statistic.help.DataSetHelp;
import com.xbongbong.pro.statistic.model.DataSetConfigModel;
import com.xbongbong.pro.statistic.model.DataSetModel;
import com.xbongbong.pro.statistic.pojo.AccumulatorPojo;
import com.xbongbong.pro.statistic.pojo.DataSetAttrReflectJoinPojo;
import com.xbongbong.pro.statistic.pojo.DataSetInfoPojo;
import com.xbongbong.pro.statistic.pojo.DataSetPermissionPojo;
import com.xbongbong.pro.statistic.pojo.DataSetRuleSamePojo;
import com.xbongbong.pro.statistic.pojo.ExecuteConfigPojo;
import com.xbongbong.pro.statistic.pojo.dto.DataSetAttrGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetAttrReflectJoinDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetAttrReflectUnionDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetBoardGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetBoardSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetCheckPermissionDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetConfigExecuteDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetConfigGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetConfigSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetCopyDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetDeleteDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetListDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetPermissionGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetPermissionSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetRenameDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetRuleDTO;
import com.xbongbong.pro.statistic.pojo.dto.DataSetSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.FormIdBusinessTypeAttrDTO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetAttrReflectJoinVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetAttrReflectUnionVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetBoardGetVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetConfigGetVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetCopyVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetListVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetPermissionGetVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetRuleVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSetSaveVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSourceAttrVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSourceObjectVO;
import com.xbongbong.pro.statistic.pojo.vo.NumberAttrVO;
import com.xbongbong.pro.statistic.service.ChartLimitService;
import com.xbongbong.pro.statistic.service.DataSetService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.base.PaymentBaseEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.sys.model.DepartmentModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zcp
 * @version v1.0
 * @since v1.0
 */
@Service("dataSetService")
public class DataSetServiceImpl implements DataSetService {
    private static final Logger LOG = LoggerFactory.getLogger(DataSetServiceImpl.class);
    @Resource
    private DataSetModel dataSetModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private DataSetHelp dataSetHelp;
    @Resource
    private DataSetConfigModel dataSetConfigModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private ChartAttrHelp chartAttrHelp;
    @Resource
    private ChartLimitService chartLimitService;
    @Resource
    private DepartmentModel departmentModel;

    @Override
    public BaseVO checkPermission(DataSetCheckPermissionDTO dataSetCheckPermissionDTO) throws XbbException {
        String corpid = dataSetCheckPermissionDTO.getCorpid();
        String operate = dataSetCheckPermissionDTO.getOperate();
        if (DataSetOperateEnum.checkNum().contains(operate)) {
            //校验套餐数量
            dataSetHelp.checkNum(corpid, true);
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        return new BaseVO();
    }

    @Override
    public DataSetListVO list(DataSetListDTO dataSetListDTO) throws XbbException {
        List<KeyValuePojo> title = new ArrayList<>();
        for (DataSetTitleEnum cache : DataSetTitleEnum.values()) {
            title.add(new KeyValuePojo(cache.getKey(), cache.getName()));
        }
        String corpid = dataSetListDTO.getCorpid();
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(BasicConstant.NINE);
        map.put(StringConstant.CORPID, corpid);
        map.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        map.put(ParameterConstant.PAGE, dataSetListDTO.getPage());
        map.put(ParameterConstant.ORDER_BY_STR, "update_time desc");
        String nameLike = dataSetListDTO.getNameLike();
        if (StringUtil.isNotEmpty(nameLike)) {
            map.put(ParameterConstant.NAME_LIKE, nameLike);
        }
        String creatorId = dataSetListDTO.getCreatorId();
        if (StringUtil.isNotEmpty(creatorId)) {
            map.put(StringConstant.CREATOR_ID, creatorId);
        }
        Map<String, String> sortMap = dataSetListDTO.getSortMap();
        if (sortMap != null && !sortMap.isEmpty()) {
            String sortField = sortMap.get(BusinessConstant.FIELD);
            String sort = sortMap.get(BasicConstant.SORT);
            if (StringUtil.isNotEmpty(sortField) && StringUtil.isNotEmpty(sort)) {
                //把驼峰转为数据库内字段名
                sortField = DataSetTitleEnum.getKeySortByKey(sortField);
                map.put(ParameterConstant.ORDER_BY_STR, String.format(SymbolConstant.SPACE_PLACE, sortField, sort));
            }
        }
        //请求来源： page跟pageSize都为null为图表中心数据集列表，  否则 为管理中心数据集列表
        boolean chartCenterFlag = Objects.isNull(dataSetListDTO.getPageSize()) && Objects.isNull(dataSetListDTO.getPage());
        PageHelper pageHelper = null;
        if(!chartCenterFlag){
            pageHelper = PageHelperUtil.getPageHelper(map, dataSetModel, dataSetListDTO.getPageSize());
            map.put("pageNum", pageHelper.getPageSize());
            map.put("start", (pageHelper.getCurrentPageNum() - 1) * pageHelper.getPageSize());
        }
        List<DataSetEntity> list = dataSetModel.findEntitysOrderByPinyin(map);
        Set<String> creatorIdSet = list.stream().map(e->e.getCreatorId()).collect(Collectors.toSet());
        //创建人
        Map<String, String> userNameMap = commonHelp.getUserNameMapByIds(corpid, creatorIdSet);
        List<DataSetInfoPojo> data = new ArrayList<>();
        // 获取部门
        Map<Long, List<Long>> subDepIdMap = departmentModel.getSubDepIdMap(corpid, false);
        UserVO loginUser = dataSetListDTO.getLoginUser();
        Set<Long> depIdIn = CustomHelp.getSubDepIds(loginUser.getDepSet(), subDepIdMap);
        //方法返回值取反一下，则true代表数量超限
        boolean numOverFlag = !dataSetHelp.checkNum(corpid, false);
        for (DataSetEntity entity : list) {
            //图表中心请求 && 无查看权限
            if(chartCenterFlag){
                if(dataSetHelp.filterPermission4DataSet(DataSetPermissionEnum.VISIBLE_SCOPE_RULE, entity, loginUser, depIdIn)) {
                    continue;
                }
                //未设置完成的忽略掉
                if(!Objects.equals(entity.getStatus(),DataSetStatusEnum.SUCCESS.getCode())){
                    continue;
                }
            }
            String executeTime = Objects.isNull(entity.getExecuteTime())? "": DateTimeUtil.getStringEpochSecond(entity.getExecuteTime());
            String creator = userNameMap.getOrDefault(entity.getCreatorId(), "");
            //登录员工是否有该数据集的编辑者权限，true无权限，false有权限
            boolean editFlag = dataSetHelp.filterPermission4DataSet(DataSetPermissionEnum.EDITABLE_RULE, entity, loginUser, depIdIn);
            //操作
            List<DsAttrValuePojo> operate = dataSetHelp.formatDataSetOperate(editFlag, numOverFlag);
            data.add(new DataSetInfoPojo(entity.getId(), entity.getName(), entity.getNameEn(), entity.getMemo(), entity.getStatus(), executeTime, entity.getPermission(), entity.getBoard(), creator, entity.getFirstPinyin(), entity.getAddTime(), entity.getUpdateTime(), operate));
        }
        return new DataSetListVO(title, data, pageHelper);
    }

    @Override
    public DataSetSaveVO save(DataSetSaveDTO dataSetSaveDTO) throws XbbException {
        UserVO loginUser = dataSetSaveDTO.getLoginUser();
        //校验套餐数量
        dataSetHelp.checkLimit(dataSetSaveDTO.getCorpid(), loginUser);
        String memo = dataSetSaveDTO.getMemo();
        if (StringUtil.isNotEmpty(memo) && memo.length() > AttrLenthConstant.NAME_MAX_LENGTH) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_240005, ErrorCodeEnum.API_ERROR_240005.getMsg(), DataSetTitleEnum.MEMO.getName(), AttrLenthConstant.NAME_MAX_LENGTH);
        }
        DataSetEntity entity = dataSetHelp.initDataSetEntity(loginUser, dataSetSaveDTO.getName(), memo);
        entity.setStatus(DataSetStatusEnum.UN_SET.getCode());
        try {
            dataSetModel.insert(entity);
        } catch (Exception e) {
            LOG.error("数据集新建失败", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263017);
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.NEW;
        String name = entity.getName();
        String opUserName = dataSetSaveDTO.getLoginUserName();
        String opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_OPERATE), opUserName, operateTypeEnum.getName(), name);
        mongoLogHelp.buildLog(dataSetSaveDTO.getCorpid(), dataSetSaveDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), name, opMemo, dataSetSaveDTO.getHttpHeader());
        DataSetSaveVO dataSetSaveVO = new DataSetSaveVO();
        dataSetSaveVO.setId(entity.getId());

        // 删除redis的key
        dataSetHelp.delPackageNumRedisKey(dataSetSaveDTO.getCorpid());
        return dataSetSaveVO;
    }

    @Override
    public BaseVO rename(DataSetRenameDTO dataSetRenameDTO) throws XbbException {
        Long id = dataSetRenameDTO.getId();
        String corpid = dataSetRenameDTO.getCorpid();
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(id, corpid, dataSetRenameDTO.getLoginUser());
        String memo = dataSetRenameDTO.getMemo();
        if (StringUtil.isNotEmpty(memo) && memo.length() > AttrLenthConstant.NAME_MAX_LENGTH) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_240005, ErrorCodeEnum.API_ERROR_240005.getMsg(), DataSetTitleEnum.MEMO.getName(), AttrLenthConstant.NAME_MAX_LENGTH);
        }
        String name = dataSetRenameDTO.getName();
        String oldName = entity.getName();
        String oldMemo = entity.getMemo();
        //日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.EDIT;
        String opUserName = dataSetRenameDTO.getLoginUserName();
        String opMemo = "";
        List<DetailLogPojo> detailLogPojoList = null;
        if (Objects.equals(oldName, name) && Objects.equals(oldMemo, memo)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263016);
        } else if (!Objects.equals(oldName, name) && !Objects.equals(oldMemo, memo)) {
            //名称或备注都变化
            opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_RENAME), opUserName, operateTypeEnum.getName(), oldName);
            DataSetLogInfoPojo oldInfo = new DataSetLogInfoPojo(oldName, oldMemo);
            DataSetLogInfoPojo newInfo = new DataSetLogInfoPojo(name, memo);
            detailLogPojoList = logHelp.detailLog4DataSetRename(corpid, oldInfo, newInfo);
        } else if (!Objects.equals(oldName, name)) {
            //仅改了名称
            opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_RENAME_NAME), opUserName, oldName, name);
        } else if (!Objects.equals(oldMemo, memo)) {
            //仅改了备注
            opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_RENAME_MEMO), opUserName, operateTypeEnum.getName(), oldName);
            DataSetLogInfoPojo oldInfo = new DataSetLogInfoPojo(oldMemo);
            DataSetLogInfoPojo newInfo = new DataSetLogInfoPojo(memo);
            detailLogPojoList = logHelp.detailLog4DataSetRename(corpid, oldInfo, newInfo);
        }
        entity.setName(name);
        entity.setMemo(memo);
        entity.setUpdateTime(DateTimeUtil.getInt());
        try {
            dataSetModel.update(entity);
        } catch (Exception e) {
            LOG.error("数据集重命名失败", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263018);
        }
        //生成日志
        mongoLogHelp.buildLog4DetailArr(detailLogPojoList, corpid, dataSetRenameDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), oldName, opMemo, dataSetRenameDTO.getHttpHeader());
        return new BaseVO();
    }

    @Override
    public BaseVO delete(DataSetDeleteDTO dataSetDeleteDTO) throws XbbException {
        Long id = dataSetDeleteDTO.getId();
        String corpid = dataSetDeleteDTO.getCorpid();
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(id, corpid, dataSetDeleteDTO.getLoginUser());
        //数据集被图表选定为数据源时，允许进行删除操作，但是会在删除时和删除后的图表中心进行提示
        entity.setDel(DelEnum.DELETE.getDel());
        entity.setUpdateTime(DateTimeUtil.getInt());
        try {
            dataSetModel.update(entity);
        } catch (Exception e) {
            LOG.error("数据集删除失败", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263019);
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
        String name = entity.getName();
        String opUserName = dataSetDeleteDTO.getLoginUserName();
        String opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_OPERATE), opUserName, operateTypeEnum.getName(), name);
        mongoLogHelp.buildLog(corpid, dataSetDeleteDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), name, opMemo, dataSetDeleteDTO.getHttpHeader());

        // 删除redis的key
        dataSetHelp.delPackageNumRedisKey(dataSetDeleteDTO.getCorpid());
        return new BaseVO();
    }

    @Override
    public DataSetCopyVO copy(DataSetCopyDTO dataSetCopyDTO) throws XbbException {
        String corpid = dataSetCopyDTO.getCorpid();
        UserVO loginUser = dataSetCopyDTO.getLoginUser();
        //校验套餐数量
        dataSetHelp.checkLimit(corpid, loginUser);
        Long id = dataSetCopyDTO.getId();
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(id, corpid, loginUser);
        String name = entity.getName();
        String copyName = name + StringConstant.HOME_PAGE_COPY_ADD;
        Integer count = BasicConstant.TWENTY;
        if (StringUtil.isNotEmpty(copyName) && copyName.length() > count) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263023, ErrorCodeEnum.API_ERROR_263023.getMsg(), DataSetTitleEnum.NAME.getName(), count);
        }
        DataSetEntity copyEntity = dataSetHelp.initDataSetEntity(loginUser, copyName, entity.getMemo());
        copyEntity.setStatus(entity.getStatus());
        copyEntity.setBoard(entity.getBoard());
        try {
            dataSetModel.insert(copyEntity);
        } catch (Exception e) {
            LOG.error("数据集复制失败", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263020);
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.COPY;
        String opUserName = dataSetCopyDTO.getLoginUserName();
        String opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_COPY), opUserName, name, copyName);
        mongoLogHelp.buildLog(corpid, dataSetCopyDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), name, opMemo, dataSetCopyDTO.getHttpHeader());
        DataSetCopyVO dataSetCopyVO = new DataSetCopyVO();
        dataSetCopyVO.setId(copyEntity.getId());

        // 删除redis的key
        dataSetHelp.delPackageNumRedisKey(dataSetCopyDTO.getCorpid());
        return dataSetCopyVO;
    }

    @Override
    public DataSetPermissionGetVO permissionGet(DataSetPermissionGetDTO dataSetPermissionGetDTO) throws XbbException {
        DataSetPermissionEnum dataSetPermissionEnum = DataSetPermissionEnum.getByAlias(dataSetPermissionGetDTO.getPermissionType());
        if (Objects.isNull(dataSetPermissionEnum)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263001);
        }
        DataSetEntity entity = dataSetHelp.getDataSetEntity(dataSetPermissionGetDTO.getId(), dataSetPermissionGetDTO.getCorpid());
        JSONObject permission = entity.getPermission();
        DataSetPermissionPojo dataSetPermissionPojo = JsonHelperUtil.parseObject(JSONObject.toJSONString(permission), DataSetPermissionPojo.class);
        DataSetPermissionGetVO dataSetPermissionGetVO = new DataSetPermissionGetVO();
        dataSetPermissionGetVO.setCreatorId(entity.getCreatorId());
        switch (dataSetPermissionEnum) {
            case EDITABLE_RULE:
                dataSetPermissionGetVO.setValue(dataSetPermissionPojo.getEditableRule());
                break;
            case VISIBLE_SCOPE_RULE:
                dataSetPermissionGetVO.setValue(dataSetPermissionPojo.getVisibleScopeRule());
                break;
            default:
                break;
        }
        return dataSetPermissionGetVO;
    }

    @Override
    public BaseVO permissionSave(DataSetPermissionSaveDTO dataSetPermissionSaveDTO) throws XbbException {
        DataSetPermissionEnum dataSetPermissionEnum = DataSetPermissionEnum.getByAlias(dataSetPermissionSaveDTO.getPermissionType());
        if (Objects.isNull(dataSetPermissionEnum)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263001);
        }
        String corpid = dataSetPermissionSaveDTO.getCorpid();
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(dataSetPermissionSaveDTO.getId(), corpid, dataSetPermissionSaveDTO.getLoginUser());
        JSONObject permission = entity.getPermission();
        DataSetPermissionPojo dataSetPermissionPojo = JsonHelperUtil.parseObject(JSONObject.toJSONString(permission), DataSetPermissionPojo.class);
        //检查value，创建人权限不能移除
        String creatorId = entity.getCreatorId();
        VisibleRulePoJo value = dataSetPermissionSaveDTO.getValue();
        if (CollectionsUtil.isEmpty(value.getUser()) || !value.getUser().contains(creatorId)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263002);
        }
        switch (dataSetPermissionEnum) {
            case EDITABLE_RULE:
                dataSetPermissionPojo.setEditableRule(value);
                break;
            case VISIBLE_SCOPE_RULE:
                dataSetPermissionPojo.setVisibleScopeRule(value);
                break;
            default:
                break;
        }
        JSONObject permissions = JsonHelperUtil.parseObject(JSONObject.toJSONString(dataSetPermissionPojo));
        entity.setPermission(permissions);
        entity.setUpdateTime(DateTimeUtil.getInt());
        try {
            dataSetModel.update(entity);
        } catch (Exception e) {
            LOG.error("权限({})设置失败:{}", dataSetPermissionEnum.getAlias(), e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263021, ErrorCodeEnum.API_ERROR_263021.getMsg(), dataSetPermissionEnum.getValue());
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.SET;
        String opUserName = dataSetPermissionSaveDTO.getLoginUserName();
        String name = entity.getName();
        String opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_SET), opUserName, operateTypeEnum.getName(), name, dataSetPermissionEnum.getValue());
        mongoLogHelp.buildLog(corpid, dataSetPermissionSaveDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), name, opMemo, dataSetPermissionSaveDTO.getHttpHeader());
        return new BaseVO();
    }

    @Override
    public DataSetConfigGetVO configGet(DataSetConfigGetDTO dataSetConfigGetDTO) throws XbbException {
        Long setId = dataSetConfigGetDTO.getId();
        String corpid = dataSetConfigGetDTO.getCorpid();
        //校验数据集是否存在
        dataSetHelp.getDataSetEntity(setId, corpid);
        //默认当做手动更新
        int type = ConfigTypeEnum.HAND.getCode();
        Integer executeRate = null;
        ExecuteConfigPojo config = null;
        DataSetConfigEntity dataSetConfigEntity = dataSetConfigModel.getByDataSetId(setId, corpid);
        if (Objects.nonNull(dataSetConfigEntity)) {
            type = dataSetConfigEntity.getType();
            executeRate = dataSetConfigEntity.getExecuteRate();
            config = JsonHelperUtil.parseObject(JSONObject.toJSONString(dataSetConfigEntity.getConfig()), ExecuteConfigPojo.class);
        }
        if (Objects.isNull(executeRate)) {
            executeRate = ConfigExecuteRateEnum.MONTH.getCode();
        }
        if (Objects.isNull(config)) {
            config = new ExecuteConfigPojo();
        }
        List<KeyAndValuePojo> typeArr = new ArrayList<>();
        for (ConfigTypeEnum cache : ConfigTypeEnum.values()) {
            KeyAndValuePojo keyAndValuePojo = new KeyAndValuePojo(cache.getCode().longValue(), cache.getName());
            typeArr.add(keyAndValuePojo);
        }
        List<KeyAndValuePojo> executeRateArr = new ArrayList<>();
        for (ConfigExecuteRateEnum cache : ConfigExecuteRateEnum.values()) {
            KeyAndValuePojo keyAndValuePojo = new KeyAndValuePojo(cache.getCode().longValue(), cache.getName());
            executeRateArr.add(keyAndValuePojo);
        }
        return new DataSetConfigGetVO(type, typeArr, executeRate, executeRateArr, config);
    }

    @Override
    public BaseVO configSave(DataSetConfigSaveDTO dataSetConfigSaveDTO) throws XbbException {
        Long setId = dataSetConfigSaveDTO.getId();
        String corpid = dataSetConfigSaveDTO.getCorpid();
        DataSetEntity dataSetEntity = dataSetHelp.getDataSetEntityByCheck(setId, corpid, dataSetConfigSaveDTO.getLoginUser());
        //校验数据集 status ，如果未完成不允许设置为自动更新
        Integer status = dataSetEntity.getStatus();
        if (Objects.equals(status, DataSetStatusEnum.UN_SET.getCode())) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263029);
        }
        //更新方式
        Integer type = dataSetConfigSaveDTO.getType();
        ConfigTypeEnum configTypeEnum = ConfigTypeEnum.getByCode(type);
        ExecuteConfigPojo config = dataSetConfigSaveDTO.getConfig();
        JSONObject configObj = null;
        StringBuilder executeMemo = new StringBuilder();
        if (Objects.isNull(configTypeEnum)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263024);
        } else if (Objects.equals(type, ConfigTypeEnum.AUTO.getCode())) {
            //更新频率
            Integer executeRate = dataSetConfigSaveDTO.getExecuteRate();
            ConfigExecuteRateEnum executeRateEnum = ConfigExecuteRateEnum.getByCode(executeRate);
            if (Objects.isNull(executeRateEnum) || Objects.isNull(config)) {
                throw new XbbException(ErrorCodeEnum.API_ERROR_263025);
            }
            executeMemo.append(executeRateEnum.getName());
            Integer day = config.getDay();
            switch (executeRateEnum) {
                case WEEK:
                    if (Objects.isNull(day) || day < BasicConstant.ONE || day > BasicConstant.SEVEN) {
                        throw new XbbException(ErrorCodeEnum.API_ERROR_263027);
                    }
                    executeMemo.append(StringUtil.intToWeek(day));
                    break;
                case MONTH:
                    if (Objects.isNull(day) || day < BasicConstant.ONE || day > BasicConstant.TWENTY_EIGHT) {
                        throw new XbbException(ErrorCodeEnum.API_ERROR_263028);
                    }
                    executeMemo.append(day);
                    executeMemo.append(DateDiffTypeEnum.DAY.getName());
                    break;
                default:
                    break;
            }
            Integer hour = config.getHour();
            if (Objects.isNull(hour) || hour > BasicConstant.TWENTY_THREE) {
                throw new XbbException(ErrorCodeEnum.API_ERROR_263026);
            }
            executeMemo.append(StringUtil.intToHour(hour));
            configObj = JsonHelperUtil.parseObject(JSONObject.toJSONString(config));
        }
        DataSetConfigEntity configEntity = dataSetConfigModel.getByDataSetId(setId, corpid);
        long now = DateTimeUtil.getInt();
        if (Objects.isNull(configEntity)) {
            if (Objects.equals(type, ConfigTypeEnum.HAND.getCode())) {
                //第一次配置且配置为手动更新，则不插入配置表
                return new BaseVO();
            }
            configEntity = new DataSetConfigEntity();
            configEntity.setCorpid(corpid);
            configEntity.setSetId(setId);
            //默认当做手动更新
            configEntity.setType(ConfigTypeEnum.HAND.getCode());
            configEntity.setCreatorId(dataSetConfigSaveDTO.getUserId());
            configEntity.setAddTime(now);
            configEntity.setDel(DelEnum.NORMAL.getDel());
        }
        configEntity.setStatus(status);
        configEntity.setType(type);
        Integer executeRate = dataSetConfigSaveDTO.getExecuteRate();
        if (Objects.nonNull(executeRate)) {
            configEntity.setExecuteRate(executeRate);
        }
        if (Objects.nonNull(configObj)) {
            configEntity.setConfig(configObj);
        }
        configEntity.setUpdateTime(now);
        try {
            if(Objects.isNull(configEntity.getId())){
                dataSetConfigModel.insert(configEntity);
            }else {
                dataSetConfigModel.update(configEntity);
            }
        } catch (Exception e) {
            LOG.error("更新规则设置失败:{}", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263021, ErrorCodeEnum.API_ERROR_263021.getMsg(), DataSetOperateEnum.EXECUTE_CONFIG.getValue());
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.SET;
        String opUserName = dataSetConfigSaveDTO.getLoginUserName();
        String name = dataSetEntity.getName();
        StringBuilder logMemo = new StringBuilder();
        logMemo.append(String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_SET), opUserName, operateTypeEnum.getName(), name, DataSetOperateEnum.EXECUTE_CONFIG.getValue()));
        logMemo.append(SymbolConstant.COLON_CHINESE);
        logMemo.append(configTypeEnum.getName());
        if (executeMemo.length() > BasicConstant.ZERO) {
            logMemo.append(SymbolConstant.SPACE);
            logMemo.append(executeMemo);
        }
        String opMemo = logMemo.toString();
        mongoLogHelp.buildLog(corpid, dataSetConfigSaveDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, dataSetEntity.getId().toString(), name, opMemo, dataSetConfigSaveDTO.getHttpHeader());
        return new BaseVO();
    }

    @Override
    public BaseVO configExecute(DataSetConfigExecuteDTO dataSetConfigExecuteDTO) throws XbbException {
        return null;
    }

    @Override
    public DataSetBoardGetVO boardGet(DataSetBoardGetDTO dataSetBoardGetDTO) throws XbbException {
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(dataSetBoardGetDTO.getId(), dataSetBoardGetDTO.getCorpid(), dataSetBoardGetDTO.getLoginUser());
        return new DataSetBoardGetVO(entity.getBoard());
    }

    @Override
    public BaseVO boardSave(DataSetBoardSaveDTO dataSetBoardSaveDTO) throws XbbException {
        Long setId = dataSetBoardSaveDTO.getId();
        String corpid = dataSetBoardSaveDTO.getCorpid();
        DataSetEntity entity = dataSetHelp.getDataSetEntityByCheck(setId, corpid, dataSetBoardSaveDTO.getLoginUser());
//        TODO 画布board格式校验，各种节点规则 校验
        Map<String, JSONObject> board = dataSetBoardSaveDTO.getBoard();
        //校验不通过都会throw出去
        JSONObject boardObj = dataSetHelp.checkBoard(board);
        //未throw说明通过校验，状态置为success
        Integer status = DataSetStatusEnum.SUCCESS.getCode();
        entity.setStatus(status);
        entity.setBoard(boardObj);
        entity.setName(dataSetBoardSaveDTO.getName());
        entity.setUpdateTime(DateTimeUtil.getInt());
        //数据集画板每次保存都清空解析过的sql
        entity.setParseSql("");
        //editFlag为true则需要变更更新时间
        if(dataSetBoardSaveDTO.getEditFlag()){
            entity.setEditTime(DateTimeUtil.getInt());
        }
        try {
            dataSetModel.update(entity);
            DataSetConfigEntity configEntity = dataSetConfigModel.getByDataSetId(setId, corpid);
            if (Objects.nonNull(configEntity) && !Objects.equals(entity.getStatus(), configEntity.getStatus())) {
                configEntity.setStatus(status);
                dataSetConfigModel.update(configEntity);
            }
        } catch (Exception e) {
            LOG.error("数据集画布设置失败", e);
            throw new XbbException(ErrorCodeEnum.API_ERROR_263022);
        }
        //生成日志
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.SET;
        String name = entity.getName();
        String opUserName = dataSetBoardSaveDTO.getLoginUserName();
        String opMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_DATA_SET_BOARD), opUserName, name);
        mongoLogHelp.buildLog(corpid, dataSetBoardSaveDTO.getUserId(), opUserName, OperateModuleTypeEnum.DATA_SET, operateTypeEnum, entity.getId().toString(), name, opMemo, dataSetBoardSaveDTO.getHttpHeader());
        return new BaseVO();
    }

    @Override
    public DataSetRuleVO rule(DataSetRuleDTO dataSetRuleDTO) throws XbbException {
        DataSetRuleVO dataSetRuleVO = new DataSetRuleVO();
        for (FieldTypeEnum cache : FieldTypeEnum.values()) {
            Integer fieldType = cache.getType();
            if (!FieldTypeEnum.showAbleFilter4DataSet(fieldType)) {
                dataSetRuleVO.addShowAble(fieldType);
            }
            if (!FieldTypeEnum.selectAbleFilter(fieldType)) {
                dataSetRuleVO.addSelectAble(fieldType);
            }
            if (!FieldTypeEnum.unionAbleFilter(fieldType)) {
                dataSetRuleVO.addUnionAble(fieldType);
            }
            //关联字段未结合字段的comboType
            if (!FieldTypeEnum.joinAbleFilter(fieldType)) {
                dataSetRuleVO.addLinkAble(fieldType);
            }
            if (!FieldTypeEnum.groupAbleFilter(fieldType)) {
                dataSetRuleVO.addGroupAble(fieldType);
            }
            if (!FieldTypeEnum.summaryAbleFilter(fieldType)) {
                dataSetRuleVO.addSummaryAble(fieldType);
            }
        }
        dataSetRuleVO.addShowAble(FieldTypeEnum.ID.getType());
        dataSetRuleVO.addShowAble(FieldTypeEnum.DATAID.getType());
        DataSetRuleSamePojo sameField = new DataSetRuleSamePojo();
        dataSetRuleVO.setSameField(sameField);
        //可关联字段的处理
        Map<String, List<Integer>> linkFields = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        linkFields.put(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType().toString(), Arrays.asList(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(),FieldTypeEnum.ID.getType()));
        linkFields.put(FieldTypeEnum.ID.getType().toString(), Arrays.asList(FieldTypeEnum.ID.getType(),FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()));
        dataSetRuleVO.setLinkFields(linkFields);
        Map<String, ArrayList<String>> unSelects = addUnSelectAbleFilter();
        dataSetRuleVO.setUnSelectAble(unSelects);
        Map<String, List<String>> unUnionAble = addUnUnionAble();
        dataSetRuleVO.setUnUnionAble(unUnionAble);
        return dataSetRuleVO;
    }

    /**
     * 业务不能合并的字段集合
     * @return java.util.Map<java.lang.String,java.util.List<java.lang.String>>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private Map<String, List<String>> addUnUnionAble() {
        List<Integer> noTbUserList = XbbRefTypeEnum.noTbUser();
        Map<String, List<String>> unUnionAble = Maps.newHashMapWithExpectedSize(noTbUserList.size());
        List<String> attrList = Arrays.asList(FieldTypeEnum.OWNERID.getAlias());
        for (Integer businessType : noTbUserList) {
            unUnionAble.put(businessType.toString(), attrList);
        }
        unUnionAble.put(String.valueOf(XbbRefTypeEnum.QUOTATION.getCode()), Arrays.asList(QuotationEnum.VERSION.getAttr()));
        return unUnionAble;
    }

    /**
     * 添加需要过滤掉的字段集合(筛选条件内)
     * @param
     * @return boolean
     * @author gzt
     * @since v1.0
     * @version v1.0
     */
    public static Map<String, ArrayList<String>> addUnSelectAbleFilter() {
        Set<Integer> productSubBusList = BIProductReformEnum.getProductSubBusList();
        ArrayList<String> productOrinals = Lists.newArrayList(SelectProductEnum.UNIT.getAttr(),SelectProductEnum.PRODUCT.getAttr(), RelatedProductConstant.COMMON_PRODUCT_SERIAL_NO_ATTR, RelatedProductConstant.LINK_MAINBUSINESS_ATTR, FieldTypeEnum.ID.getAlias(),FieldTypeEnum.DATAID.getAlias(),RelativeProductEnum.PRODUCT_ID.getSaasAttr());
        Map<String, ArrayList<String>> productBusMap = Maps.newHashMap();
        productSubBusList.forEach(productBus->{
            productBusMap.put(productBus.toString(),productOrinals);
        });
        //产品表供应商字段类型定义text数据实际存成数组,需过滤掉
        productBusMap.put(String.valueOf(XbbRefTypeEnum.PRODUCT.getCode()), Lists.newArrayList(ProductEnum.SUPPLIER.getAttr()));
        ArrayList<String> arrayList = Lists.newArrayList(FieldTypeEnum.ID.getAlias(), FieldTypeEnum.DATAID.getAlias());
        for (XbbTableRefEnum value : XbbTableRefEnum.values()) {
            String key = String.valueOf(value.getCode());
            if (Objects.equals(value, XbbRefTypeEnum.PAYMENT)) {
                //应收款来源单据禁止筛选
                arrayList.add(PaymentBaseEnum.SOURCE.getAttr());
            }
            //过滤掉前面加过的
            if(!productBusMap.containsKey(key)){
                productBusMap.put(key, arrayList);
            }
        }
        return productBusMap;
    }

    @Override
    public DataSetAttrReflectUnionVO attrReflectUnion(DataSetAttrReflectUnionDTO dataSetAttrReflectUnionDTO) throws XbbException {
        List<DataSetNodeFieldPojo> field = dataSetAttrReflectUnionDTO.getField();

        //做两个集合
        //1.key 为 源Attr   把原来的字段新attr赋值上去
        // 2.formId 对应的原始originalAttr->attr
        //时间类的放在date字段上
        //保证此处只被调用一次
        AccumulatorPojo accumulatorPojo = new AccumulatorPojo();
        //key : originalAttr +"-"+ formId
        Map<String,Object> selectedMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //formId:<originalAttr :attr>
        Map<String,Map<String,String>>  selectedByFormIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> attrList = new ArrayList<>();
        Map<String,String> linkAttrMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (DataSetNodeFieldPojo fieldPojo : field) {
            Map<String, BiExplainPojo> srcB = fieldPojo.getSrcB();
            for (Map.Entry<String, BiExplainPojo> entry : srcB.entrySet()) {
                BiExplainPojo biExplainPojo = entry.getValue();
                if (Objects.isNull(biExplainPojo)) {
                    continue;
                }
                //这里不要判断OriginalAttr存在给attr,因为前端第一次默认给的就是OriginalAttr，和其他地方逻辑不一致
                String attr = CustomHelp.reflectAttr(biExplainPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
                attrList.add(attr);
                Integer fieldType = fieldPojo.getFieldType();
                if (linkFieldType(fieldType)) {
                    String linkedText = fieldPojo.getLinkedText();
                    if (StringUtil.isNotEmpty(linkedText)) {
                        //这里取得的都是主的
                        JSONObject linkedAttr = fieldPojo.getLinkedAttr();
//                        BiExplainPojo linkPojo = new BiExplainPojo(linkedText, linkedAttr.getString("attr"), linkedAttr.getString("attrType"), linkedAttr.getInteger("fieldType"), linkedAttr.getLong("formId"), linkedAttr.getString("attrName"));
                        BiExplainPojo linkPojo = linkedAttr.toJavaObject(BiExplainPojo.class);
                        //OriginalAttr 存在则证明前面过过层级
                        if(StringUtil.isNotEmpty(linkPojo.getOriginalAttr())){
                            linkPojo.setOriginalAttr(linkPojo.getAttr());
                        }
                        String attrLink = CustomHelp.reflectAttr(linkPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
                        //这里的attr是原始attr
                        linkAttrMap.put(attr, attrLink);
                    }
                }
                //每列映射出一个字段即可（每列的字段类型是一致的）
                break;
            }
        }

        
        List<String> hideList = new ArrayList<>();
        List<DataSetNodeFieldPojo> hideField = dataSetAttrReflectUnionDTO.getHide();
        try {
            for (DataSetNodeFieldPojo fieldPojo : hideField) {
                Map<String, BiExplainPojo> srcB = fieldPojo.getSrcB();
                for (Map.Entry<String, BiExplainPojo> entry : srcB.entrySet()) {
                    BiExplainPojo biExplainPojo = entry.getValue();
                    if (Objects.isNull(biExplainPojo)) {
                        continue;
                    }
                    //保证和主的formId一致
                    if(!Objects.equals(fieldPojo.getFormId(),biExplainPojo.getFormId())){
                        continue;
                    }
                    String attr = "";
                   /* if(linkAttrSet.contains(biExplainPojo.getOriginalAttr())){
                        
                    }else {
                    }*/
                    //这里不要判断OriginalAttr存在给attr,因为前端第一次默认给的就是OriginalAttr，和其他地方逻辑不一致
                    attr = CustomHelp.reflectAttr(biExplainPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
                    //用户选的不再重复放置
                    /*if (attrList.contains(attr)) {
                        attr = "";
                    }*/
                    //前端可能传了多个相同的hide，一个是当前的，一个是上衣层级的
                    if(hideList.contains(attr)){
                        attr = "";
                    }
                    hideList.add(attr);
                    //每列映射出一个字段即可（每列的字段类型是一致的）
                    break;
                }
            }
        } catch (Exception e) {
            LOG.error(BiErrorCodeEnum.API_ERROR_241034.getMsg(),e);
            throw new XbbException(BiErrorCodeEnum.API_ERROR_241034);
        }
        return new DataSetAttrReflectUnionVO(attrList,hideList,linkAttrMap);
    }

    @Override
    public DataSetAttrReflectJoinVO attrReflectJoin(DataSetAttrReflectJoinDTO dataSetAttrReflectJoinDTO) throws XbbException {
        DataSetJoinEnum joinEnum = DataSetJoinEnum.getByAlias(dataSetAttrReflectJoinDTO.getJoin());
        if (Objects.isNull(joinEnum)) {
            throw new XbbException(ErrorCodeEnum.API_ERROR_263007);
        }
        //做两个集合
        //1.key 为 源Attr   把原来的字段新attr赋值上去
        // 2.formId 对应的原始originalAttr->attr
        //时间类的放在date字段上
        //保证此处只被调用一次
        AccumulatorPojo accumulatorPojo = new AccumulatorPojo();
        //key : originalAttr +"-"+ formId
        Map<String,Object> selectedMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //formId:<originalAttr :attr>
        Map<String,Map<String,String>>  selectedByFormIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Integer mergeLinkField = dataSetAttrReflectJoinDTO.getMergeLinkField();
        //需要合并连接字段
        boolean mergeFlag = Objects.equals(mergeLinkField, BasicConstant.ONE);
        //生成新的表头 field，不管是何种连接，表头都是左右表拼到一起形成。但是要结合 mergeLinkField 控制左右表内连接字段的status
        //拼接时先拼左表字段，再拼右表
        List<DataSetNodeFieldPojo> list = new ArrayList<>();
        Map<String,DataSetNodeFieldPojo>  linkAttrMap  = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //dto内已校验左右字段是否为空
        DataSetAttrReflectJoinPojo left = dataSetAttrReflectJoinDTO.getLeft();
        DataSetAttrReflectJoinPojo right = dataSetAttrReflectJoinDTO.getRight();
        switch (joinEnum) {
            //左连接用左表、右连接用右表，内连接统一用左表
            case LEFT:
            case INNER:
                //左连接、内连接，左表字段肯定都启用，如果需要合并则合并右表字段
                noMerge(DataSetJoinEnum.LEFT, list, selectedMap, selectedByFormIdMap, accumulatorPojo, left,linkAttrMap, dataSetAttrReflectJoinDTO.getLeftAttr());
                //左连接、内连接，如果需要合并则合并右表字段
                List<String> rightAttr = dataSetAttrReflectJoinDTO.getRightAttr();
                merge(DataSetJoinEnum.RIGHT, list, selectedMap, selectedByFormIdMap, accumulatorPojo, right, mergeFlag, rightAttr,linkAttrMap);
                break;
            case RIGHT:
                //右连接，如果需要合并则合并左表字段
                List<String> leftAttr = dataSetAttrReflectJoinDTO.getLeftAttr();
                merge(DataSetJoinEnum.LEFT, list, selectedMap, selectedByFormIdMap, accumulatorPojo, left, mergeFlag, leftAttr, linkAttrMap);
                //右连接，右表字段肯定都启用，如果需要合并则合并左表字段
                noMerge(DataSetJoinEnum.RIGHT, list, selectedMap, selectedByFormIdMap, accumulatorPojo, right, linkAttrMap, dataSetAttrReflectJoinDTO.getRightAttr());
                break;
            default:
                break;
        }

        //移除已经在的，已经在list内的就不用再加一遍关联隐藏字段
        if(!linkAttrMap.isEmpty() && CollectionsUtil.isNotEmpty(list)){
            for (DataSetNodeFieldPojo data : list) {
                String key = data.getFormId() + "_" + data.getOriginalAttr();
                linkAttrMap.remove(key);
            }
        }
        if(!linkAttrMap.isEmpty()){
            list.addAll(linkAttrMap.values());
        }
        
        //隐藏逻辑字段的处理 
        List<DataSetNodeFieldPojo> hidelist = new ArrayList<>();
        DataSetAttrReflectJoinPojo hideLeft = dataSetAttrReflectJoinDTO.getHideLeft();
        DataSetAttrReflectJoinPojo hideRight = dataSetAttrReflectJoinDTO.getHideRight();
        if(CollectionsUtil.isNotEmpty(hideLeft.getField())){
            // 去重处理，用户选过的就不再塞默认逻辑  跳过
//            reMoveRedundant(left, hideLeft);
            noMerge(DataSetJoinEnum.LEFT, hidelist, selectedMap, selectedByFormIdMap, accumulatorPojo, hideLeft,linkAttrMap, dataSetAttrReflectJoinDTO.getLeftAttr());
        }
        if(CollectionsUtil.isNotEmpty(hideRight.getField())){
//            reMoveRedundant(right, hideRight);
            noMerge(DataSetJoinEnum.RIGHT, hidelist, selectedMap, selectedByFormIdMap, accumulatorPojo, hideRight,linkAttrMap, dataSetAttrReflectJoinDTO.getRightAttr());
        }
        
        return new DataSetAttrReflectJoinVO(list,hidelist);
    }

    /**
     * 去除重复字段(去重处理，用户选过的就不再塞默认逻辑  跳过)
     * @param left
     * @param hideLeft
     */
    private void reMoveRedundant(DataSetAttrReflectJoinPojo left, DataSetAttrReflectJoinPojo hideLeft) {
        List<DataSetNodeFieldPojo> viewField = left.getField();
        Set<String>  attrCoo = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (DataSetNodeFieldPojo dataSetNodeFieldPojo : viewField) {
            attrCoo.add(dataSetNodeFieldPojo.getAttr());
            if(Objects.equals(dataSetNodeFieldPojo.getFieldType(),FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())){
                //关联单选也移除
                attrCoo.add(dataSetNodeFieldPojo.getLinkedText());
            }
        }
        List<DataSetNodeFieldPojo> hideField = hideLeft.getField();
        hideField.removeIf(dataSetNodeFieldPojo -> attrCoo.contains(dataSetNodeFieldPojo.getAttr()));
        hideLeft.setField(hideField);
    }

    @Override
    public DataSourceAttrVO sourceAttrAttr(DataSetAttrGetDTO dataSetAttrGetDTO) throws XbbException{
        String corpid = dataSetAttrGetDTO.getCorpid();
        //获取数据集节点field
        List<FieldAttrEntity> fieldList = new ArrayList<>();
        Long dataSetId = dataSetAttrGetDTO.getId();
        DataSetEntity entity = dataSetHelp.getDsNodeField(corpid, dataSetId, fieldList);

        //TODO =================================以下方法拆出去
        //可展示字段，表头/穿透
        DataSourceObjectVO showDataSourceObjectVO = new DataSourceObjectVO();
        //可筛选的    paasFormExplainService.screenList
        DataSourceObjectVO selectDataSourceObjectVO = new DataSourceObjectVO();
        //分组/分类字段
        DataSourceObjectVO groupDataSourceObjectVO = new DataSourceObjectVO();
        //查询表可汇总的
        DataSourceObjectVO summaryDataSourceObjectVO = new DataSourceObjectVO();
        //仪表盘需要的字段
        DataSourceObjectVO dashboardSourceObjectVO = new DataSourceObjectVO();
        //统计表可汇总的
        DataSourceObjectVO querySummaryDataSourceObjectVo = new DataSourceObjectVO();
        //归属人
        DataSourceObjectVO belongDataSourceObjectVO = new DataSourceObjectVO();
        //时间类型
        DataSourceObjectVO timeDataSourceObjectVO = new DataSourceObjectVO();
        //关联字段
        DataSourceObjectVO linkDataSourceObjectVO = new DataSourceObjectVO();
        //地址类型
        DataSourceObjectVO addressDataSourceObjectVO = new DataSourceObjectVO();
        //漏斗维度类型
        DataSourceObjectVO funnelDataSourceObjectVO = new DataSourceObjectVO();
        List<Integer> noSearchIdList = FieldTypeEnum.esaliasTypeList().getNoSearchIdList();
        List<Integer> numIdList = FieldTypeEnum.esaliasTypeList().getNumIdList();
        List<Integer> belongIdList = FieldTypeEnum.esaliasTypeList().getBelongIdList();
        List<Integer> timeIdList = FieldTypeEnum.esaliasTypeList().getTimeIdList();
        List<Integer> addressIdList = FieldTypeEnum.esaliasTypeList().getAddressIdList();
        List<Integer> funnelIdList = FieldTypeEnum.esaliasTypeList().getFunnelIdList();
        DataSourceAttrVO dataSourceAttrVO = new DataSourceAttrVO();
        Integer chartType = dataSetAttrGetDTO.getChartType();
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMapByList(fieldList, null);
        List<String> linkedNames = new ArrayList<>();
        List<FieldAttrEntity> groupExplainList = new ArrayList<>((ArrayList) CloneUtil.deepClone(fieldList));
        List<FieldAttrEntity> selectExplainList = new ArrayList<>((ArrayList) CloneUtil.deepClone(fieldList));
        //子表单和数组格式不允许分组以及关联
        chartAttrHelp.filterGroupList(chartType,  groupExplainList,null);
        chartAttrHelp.filterSelectList(chartType,  selectExplainList,null);
        //saasMark, businessType, formId  给空字段中获取      appId 内层字段也为空
        chartAttrHelp.setDataSourceObjectVO(groupExplainList, groupDataSourceObjectVO, null, null, null, corpid, null, explainMap, ChartAttrTypeEnum.GROUP.getIndex(), chartType,true);
        chartAttrHelp.setDataSourceObjectVO(selectExplainList, selectDataSourceObjectVO, null, null, null, corpid, null, explainMap, ChartAttrTypeEnum.SELECT.getIndex(), chartType,true);
        List<Integer> abnormalStatusList = DataSetFieldStatusEnum.abnormalStatusList();
        for (FieldAttrEntity fieldAttrEntity  : fieldList) {
            if (abnormalStatusList.contains(fieldAttrEntity.getStatus())) {
                continue;
            }
            if(Objects.equals(FieldTypeEnum.ID.getType(),fieldAttrEntity.getFieldType())){
                //图表中心去除id的展示
                continue;
            }
//            FieldAttrEntity fieldAttrEntity = explainIt.next();
            // 字段回收站处理
            FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldAttrEntity.getFieldType());
            //  distributorFlag 
            if(chartAttrHelp.showExplainFliter(chartType, fieldAttrEntity.getBusinessType(), false, fieldAttrEntity)){
                continue;
            }
            fieldAttrEntity.setDataSetId(dataSetId );
            //图表中心使用时背景色置空
            fieldAttrEntity.setBgColor(null);
            //TODO  saasMark, appId 先给null
            chartAttrHelp.classifyField(dataSourceAttrVO, corpid, 0, chartType, showDataSourceObjectVO, summaryDataSourceObjectVO, querySummaryDataSourceObjectVo, belongDataSourceObjectVO, timeDataSourceObjectVO, addressDataSourceObjectVO, funnelDataSourceObjectVO, fieldAttrEntity.getFormId(), fieldAttrEntity.getBusinessType(), null, explainMap, noSearchIdList, numIdList, belongIdList, timeIdList, addressIdList, funnelIdList, fieldAttrEntity.getSaasMark(), null, linkedNames, fieldAttrEntity, fieldTypeEnum,true);
        }
        //开启ck，且传入的图表类型支持钻取
        boolean drillFlag = ChartTypeEnum.supportDrillSet(chartLimitService.getCkFlag(), chartType);
        //saasMark, businessType, formId  给空，从字段中获取      appId 内层字段也为空
        chartAttrHelp.setDashBoardVO(corpid, null, null, null, null, chartType, showDataSourceObjectVO, groupDataSourceObjectVO, dashboardSourceObjectVO, numIdList, belongIdList, drillFlag);
        //计数字段
        chartAttrHelp.setCountField(chartType, summaryDataSourceObjectVO, dashboardSourceObjectVO, null);
        
        
        chartAttrHelp.setName(showDataSourceObjectVO, selectDataSourceObjectVO, groupDataSourceObjectVO, summaryDataSourceObjectVO, dashboardSourceObjectVO, querySummaryDataSourceObjectVo, belongDataSourceObjectVO, timeDataSourceObjectVO, linkDataSourceObjectVO, addressDataSourceObjectVO, funnelDataSourceObjectVO, entity.getName());
        chartAttrHelp.setDataSourceVO(dataSourceAttrVO, showDataSourceObjectVO, selectDataSourceObjectVO, groupDataSourceObjectVO, summaryDataSourceObjectVO, dashboardSourceObjectVO, querySummaryDataSourceObjectVo, belongDataSourceObjectVO, timeDataSourceObjectVO, linkDataSourceObjectVO, addressDataSourceObjectVO, funnelDataSourceObjectVO, drillFlag);
        return dataSourceAttrVO;
    }
    
    
    /**
     *
     * @param dataSetJoinEnum 处理的是左表or右表
     * @param list 映射后的连接字段
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @param leftOrRight 左表或右表的节点
     * @param joinAttr 左右连接字段
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void noMerge(DataSetJoinEnum dataSetJoinEnum, List<DataSetNodeFieldPojo> list, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, DataSetAttrReflectJoinPojo leftOrRight, Map<String,DataSetNodeFieldPojo>  linkAttrMap, List<String> joinAttr) {
        List<DataSetNodeFieldPojo> field = leftOrRight.getField();
        Map<String,DataSetNodeFieldPojo>  oriMap = new HashMap<>(field.size());
        List<DataSetNodeFieldPojo> sortField = new ArrayList<>(field.size());
        for (DataSetNodeFieldPojo dataSetNodeFieldPojo : field) {
            oriMap.put(dataSetNodeFieldPojo.getAttr(),dataSetNodeFieldPojo);
            if (linkFieldType(dataSetNodeFieldPojo.getFieldType())) {
                sortField.add(dataSetNodeFieldPojo);
            }
        }
        String id = leftOrRight.getId();
        //左、右连接节点的节点名称
        String name = leftOrRight.getName();
        boolean emptyFlag = StringUtil.isEmpty(name);
        int status = DataSetFieldStatusEnum.NORMAL.getCode();
        if(CollectionsUtil.isNotEmpty(sortField)){
            extField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, linkAttrMap, joinAttr, sortField, id, name, emptyFlag, status, oriMap);
            field.removeAll(sortField);
            extField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, linkAttrMap, joinAttr, field, id, name, emptyFlag, status, oriMap);
        }else {
            extField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, linkAttrMap, joinAttr, field, id, name, emptyFlag, status, oriMap);
        }
    }

    private void extField(DataSetJoinEnum dataSetJoinEnum, List<DataSetNodeFieldPojo> list, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, Map<String, DataSetNodeFieldPojo> linkAttrMap, List<String> joinAttr, List<DataSetNodeFieldPojo> field, String id, String name, boolean emptyFlag, int status, Map<String, DataSetNodeFieldPojo> oriMap) {
        for (DataSetNodeFieldPojo dataSetNodeFieldPojo : field) {
            if (list.size() >= DataSetConstant.MAX_FIELD_COUNT) {
                //超过100个的，默认置为不启用
                status = DataSetFieldStatusEnum.CLOSE.getCode();
            }
            //前面处理过被移除掉了
            if (!oriMap.containsKey(dataSetNodeFieldPojo.getAttr())) {
                //关联字段前面处理过了
                continue;
            }
            extFieldPojo(dataSetJoinEnum, joinAttr, selectedMap, selectedByFormIdMap, accumulatorPojo, dataSetNodeFieldPojo, id, status, emptyFlag, name, list, linkAttrMap, oriMap);
        }
    }


    /**
     *
     * @param dataSetJoinEnum 处理的是左表or右表
     * @param list
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @param leftOrRight 左表或右表的节点
     * @param mergeFlag
     * @param mergeAttr
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void merge(DataSetJoinEnum dataSetJoinEnum, List<DataSetNodeFieldPojo> list, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, DataSetAttrReflectJoinPojo leftOrRight, boolean mergeFlag, List<String> mergeAttr,Map<String,DataSetNodeFieldPojo>  linkAttrMap) {
        String id = leftOrRight.getId();
        List<DataSetNodeFieldPojo> field = leftOrRight.getField();
        //左、右连接节点的节点名称
        String name = leftOrRight.getName();
        boolean emptyFlag = StringUtil.isEmpty(name);
        int status;
        Map<String,DataSetNodeFieldPojo>  oriMap = new HashMap<>(field.size());
        List<DataSetNodeFieldPojo> sortField = new ArrayList<>(field.size());
        for (DataSetNodeFieldPojo dataSetNodeFieldPojo : field) {
            oriMap.put(dataSetNodeFieldPojo.getAttr(),dataSetNodeFieldPojo);
            if (linkFieldType(dataSetNodeFieldPojo.getFieldType())) {
                sortField.add(dataSetNodeFieldPojo);
            }
        }
        if(CollectionsUtil.isNotEmpty(sortField)){
            extMergeField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, mergeFlag, mergeAttr, linkAttrMap, id, sortField, name, emptyFlag, oriMap);
            field.removeAll(sortField);
            extMergeField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, mergeFlag, mergeAttr, linkAttrMap, id, field, name, emptyFlag, oriMap);
        }else {
            extMergeField(dataSetJoinEnum, list, selectedMap, selectedByFormIdMap, accumulatorPojo, mergeFlag, mergeAttr, linkAttrMap, id, field, name, emptyFlag, oriMap);
        }
    }

    private void extMergeField(DataSetJoinEnum dataSetJoinEnum, List<DataSetNodeFieldPojo> list, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, boolean mergeFlag, List<String> mergeAttr, Map<String, DataSetNodeFieldPojo> linkAttrMap, String id, List<DataSetNodeFieldPojo> field, String name, boolean emptyFlag, Map<String, DataSetNodeFieldPojo> oriMap) {
        int status;
        for (DataSetNodeFieldPojo dataSetNodeFieldPojo : field) {
            boolean hideFlag = mergeFlag && mergeAttr.contains(dataSetNodeFieldPojo.getAttr());
            if (hideFlag) {
                //左连接和内连接，如果需要合并则把连接的右表连接字段status置为0；相反，右连接如果需要合并则把连接的左表连接字段status置为0
                status = DataSetFieldStatusEnum.LINK_HIDE.getCode();
            } else {
                //超过100个的，默认置为不启用
                status = list.size() >= DataSetConstant.MAX_FIELD_COUNT ? DataSetFieldStatusEnum.CLOSE.getCode() : DataSetFieldStatusEnum.NORMAL.getCode();
            }
            //前面处理过被移除掉了
            if(!oriMap.containsKey(dataSetNodeFieldPojo.getAttr())){
                continue;
            }
            extFieldPojo(dataSetJoinEnum, mergeAttr, selectedMap, selectedByFormIdMap, accumulatorPojo, dataSetNodeFieldPojo, id, status, emptyFlag, name, list, linkAttrMap, oriMap);
        }
    }

    /**
     * 扩充整理字段
     * @param dataSetJoinEnum 处理的是左表or右表
     * @param joinAttr 连接字段
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @param next  field
     * @param id  节点id
     * @param status   @see com.xbongbong.paas.enums.bi.DataSetFieldStatusEnum
     * @param emptyFlag 节点名称是否为空
     * @param name  左、右连接节点的节点名称
     * @param list  载体
     * @param linkAttrMap 关联字段
     * @return
     */
    private DataSetNodeFieldPojo extFieldPojo(DataSetJoinEnum dataSetJoinEnum, List<String> joinAttr, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, DataSetNodeFieldPojo next, String id, Integer status, boolean emptyFlag, String name, List<DataSetNodeFieldPojo> list, Map<String, DataSetNodeFieldPojo> linkAttrMap, Map<String,DataSetNodeFieldPojo>  oriMap) {
        //上一节点已经映射后的attr，对当前节点来说还未映射，所以此处直接把 DataSetNodeFieldPojo 转为参与映射的实体，把其DataSetNodeFieldPojo.attr映射出新的attr值
        //字段映射需要的BiExplainPojo和节点DataSetNodeFieldPojo字段基本一致，且映射只用到几个核心字段
        BiExplainPojo biExplainPojo = JsonHelperUtil.parseObject(JSONObject.toJSONString(next), BiExplainPojo.class);
        //OriginalAttr 存在则证明前面过过层级
        if(StringUtil.isNotEmpty(biExplainPojo.getOriginalAttr())){
            biExplainPojo.setOriginalAttr(next.getAttr());
        }
        //要用映射之前的attr
        String bgColor = dealWithBgColor(dataSetJoinEnum, joinAttr, next);
        String attr = CustomHelp.reflectAttr(biExplainPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
        Map<String, BiExplainPojo> srcB = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        biExplainPojo.setAttr(attr);
        srcB.put(id, biExplainPojo);
        //如果status为常规显示且上一个节点传了status则使用上一个节点传下来的
        status = (Objects.equals(status, DataSetFieldStatusEnum.NORMAL.getCode()) && Objects.nonNull(next.getStatus())) ? next.getStatus() : status;
        //originalAttr 应该取过过映射方法的
        DataSetNodeFieldPojo dataSetNodeFieldPojo = new DataSetNodeFieldPojo(status, bgColor, next.getFormId(), biExplainPojo.getOriginalAttr(), attr, next.getAttrName(), next.getFieldType(), next.getAttrType(), next.getAmountFlag());
        dataSetNodeFieldPojo.setSrcB(srcB);
        dataSetNodeFieldPojo.setBusinessType(next.getBusinessType());
        dataSetNodeFieldPojo.setScreenType(next.getScreenType());
        dataSetNodeFieldPojo.setSaasMark(next.getSaasMark());
        dataSetNodeFieldPojo.setAccuracy(next.getAccuracy());
        dataSetNodeFieldPojo.setGroupingUsed(next.getGroupingUsed());
        dataSetNodeFieldPojo.setPercentUsed(next.getPercentUsed());
        dataSetNodeFieldPojo.setItems(next.getItems());
        dataSetNodeFieldPojo.setIsOpen(next.getIsOpen());
        //日期需要放dateType
        if(FieldTypeEnum.isDateTimeByFieldType(next.getFieldType())){
            dataSetNodeFieldPojo.setDateType(next.getDateType());
        }
        if (FieldTypeEnum.isSubFormType(next.getFieldType())) {
            SubFormPoJo subForm = next.getSubForm();
            for (FieldAttrEntity item : subForm.getItems()) {
                item.setParentAttr(attr);
                item.setBgColor(bgColor);
            }
            dataSetNodeFieldPojo.setSubForm(subForm);
        }
        if (emptyFlag) {
            dataSetNodeFieldPojo.setAttrName(dataSetNodeFieldPojo.getAttrName());
        } else {
            dataSetNodeFieldPojo.setAttrName(name + SymbolConstant.Tilde_ENGLISH + dataSetNodeFieldPojo.getAttrName());
        }
        //添加关联字段
        Integer fieldType = next.getFieldType();
        List<DataSetNodeFieldPojo> linkList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (linkFieldType(fieldType)) {
            String linkedText = next.getLinkedText();
            if (StringUtil.isNotEmpty(linkedText)) {
                if (oriMap.containsKey(linkedText)) {
                    DataSetNodeFieldPojo pojo = extFieldPojo(dataSetJoinEnum, joinAttr, selectedMap, selectedByFormIdMap, accumulatorPojo, oriMap.get(linkedText), id, status, emptyFlag, name, linkList, linkAttrMap, oriMap);
                    dataSetNodeFieldPojo.setLinkedText(pojo.getAttr());
                    oriMap.remove(linkedText);
                }else {
                    //第一层才会走这里
                    addlinkText(list, selectedMap, selectedByFormIdMap, accumulatorPojo, id, next, dataSetNodeFieldPojo, linkAttrMap,oriMap);
                }
            }
        }
        list.add(dataSetNodeFieldPojo);
        if(CollectionsUtil.isNotEmpty(linkList)){
            list.addAll(linkList);
        }
        return dataSetNodeFieldPojo;
    }

    private boolean linkFieldType(Integer fieldType) {
        return Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) || Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_MULTI.getType())
                || Objects.equals(fieldType, FieldTypeEnum.LINK_RECEIVER.getType()) || FieldTypeEnum.BIRTHDAY.getType().equals(fieldType);
    }

    private void addlinkText(List<DataSetNodeFieldPojo> list, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo, String id, DataSetNodeFieldPojo next, DataSetNodeFieldPojo dataSetNodeFieldPojo, Map<String, DataSetNodeFieldPojo> linkAttrMap, Map<String, DataSetNodeFieldPojo> oriMap) {
        Integer fieldType = next.getFieldType();
        if (linkFieldType(fieldType)) {
            String linkedText = next.getLinkedText();
            if (StringUtil.isNotEmpty(linkedText)) {
                JSONObject linkedAttr = next.getLinkedAttr();
                dataSetNodeFieldPojo.setLinkedAttr(linkedAttr);
                //第一次进来originalAttr是没有的，后面是上一层级的
                String attr = linkedAttr.getString("attr");
                BiExplainPojo linkPojo = new BiExplainPojo(linkedText, attr, linkedAttr.getString("attrType"), linkedAttr.getInteger("fieldType"), linkedAttr.getLong("formId"), linkedAttr.getString("attrName"));
                String attrLink = CustomHelp.reflectAttr(linkPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
                dataSetNodeFieldPojo.setLinkedText(attrLink);
                linkedAttr.put("attr",attrLink);
                linkedAttr.put("originalAttr",attr);
                //隐藏字段的追加
                DataSetNodeFieldPojo linkFieldPojo = new DataSetNodeFieldPojo(DataSetFieldStatusEnum.LINK_HIDE.getCode(), dataSetNodeFieldPojo.getBgColor(), linkPojo.getFormId(), linkPojo.getOriginalAttr(), attrLink, linkPojo.getAttrName(), linkPojo.getFieldType(), linkPojo.getAttrType(), next.getAmountFlag());
                Map<String, BiExplainPojo> linkSrcB = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                linkPojo.setAttr(attrLink);
                linkPojo.setIsOpen(0);
                linkSrcB.put(id, linkPojo);
                linkFieldPojo.setSrcB(linkSrcB);
                linkFieldPojo.setBusinessType(next.getBusinessType());
                linkFieldPojo.setIsOpen(0);
                //ScreenType
//            linkFieldPojo.setScreenType();
//            list.add(linkFieldPojo);
                //这里的attr是原始attr
                linkAttrMap.put(linkedAttr.getLong("formId") + "_" + attr, linkFieldPojo);
            }
        }
    }

    @Override
    public NumberAttrVO searchDsNumberAttr(FormIdBusinessTypeAttrDTO formIdBusinessTypeAttrDTO) throws XbbException {
        //解析入参
        JSONObject formIdBusinessTypeList = formIdBusinessTypeAttrDTO.getFormIdBusinessTypeList();
        Long dsId = null;
        Integer chartType = null;
        try{
            for (Map.Entry<String, Object> objectEntry : formIdBusinessTypeList.entrySet()) {
                //数据集只会传递一个  {数据集id：图表type}
                dsId = Long.parseLong(objectEntry.getKey());
                chartType = Integer.parseInt(String.valueOf(objectEntry.getValue()));
                break;
            }
        }catch (Exception e){
            throw new XbbException(ErrorCodeEnum.API_ERROR_263005);
        }

        //获取节点字段
        List<FieldAttrEntity> fieldList = new ArrayList<>();
        DataSetEntity dataSetEntity = dataSetHelp.getDsNodeField(formIdBusinessTypeAttrDTO.getCorpid(), dsId, fieldList);

        //拆分不同formId的字段
        Map<Long,List<FieldAttrEntity>> formIdByFieldListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (FieldAttrEntity fieldAttrEntity : fieldList) {
            Long formId = fieldAttrEntity.getFormId();
            if(formIdByFieldListMap.containsKey(formId)){
                List<FieldAttrEntity> fieldAttrEntities = formIdByFieldListMap.get(formId);
                fieldAttrEntities.add(fieldAttrEntity);
            }else{
                List<FieldAttrEntity> fieldAttrEntityList = new ArrayList<>();
                fieldAttrEntityList.add(fieldAttrEntity);
                formIdByFieldListMap.put(formId,fieldAttrEntityList);
            }
        }

        //组装vo数据
        NumberAttrVO numberAttrVO = new NumberAttrVO();
        for (Map.Entry<Long, List<FieldAttrEntity>> listEntry : formIdByFieldListMap.entrySet()) {
            List<FieldAttrEntity> fieldAttrEntities = listEntry.getValue();

            fieldAttrEntities.removeIf(explain -> Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), explain.getBusinessType()) && (Objects.equals(explain.getFieldType(),FieldTypeEnum.WORK_ORDER_STAGE.getType())
                    || Objects.equals(explain.getFieldType(),FieldTypeEnum.WORK_ORDER_STAGE_NAME.getType())));

            fieldAttrEntities.removeIf(explain ->
                    (explain.getScreenType()!=null && explain.getScreenType() < ScreenTypeEnum.SCREEN_SHOW.getType()) || FieldTypeEnum.baseFilter(explain.getFieldType())
                            ||  !FieldTypeEnum.getComputedType().contains(explain.getFieldType())|| Objects.equals(explain.getIsOpen(), 0) || Objects.equals(explain.getIsOpen(), 2)  || Objects.equals(explain.getFieldType(), FieldTypeEnum.COMBO_LINK_BUSINESS.getType())
            );
            DataSourceObjectVO dataSourceObjectVO =new DataSourceObjectVO();
            dataSourceObjectVO.setName(dataSetEntity.getName());
            dataSourceObjectVO.setFormId(listEntry.getKey());
            dataSourceObjectVO.setFieldList(fieldAttrEntities);
            chartAttrHelp.groupByFieldType(dataSourceObjectVO);
            numberAttrVO.addNumberAble(dataSourceObjectVO);
        }
        return numberAttrVO;
    }

    /**
     * 处理连接节点表头背景颜色
     * @param dataSetJoinEnum 左右表
     * @param joinAttr 连接字段
     * @param next 具体字段
     * @return java.lang.String
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private String dealWithBgColor(DataSetJoinEnum dataSetJoinEnum, List<String> joinAttr, DataSetNodeFieldPojo next) {
        String color = "";
        if (joinAttr.contains(next.getAttr())) {
            //如果是左右表连接字段，则直接用连接字段的背景色
            color = DataSetFieldBgColorEnum.JOIN_FIELD.getColor();
        } else {
            switch (dataSetJoinEnum) {
                case LEFT:
                    color = DataSetFieldBgColorEnum.LEFT_FIELD.getColor();
                    break;
                case RIGHT:
                    color = DataSetFieldBgColorEnum.RIGHT_FIELD.getColor();
                    break;
                default:
                    break;
            }
        }
        return color;
    }
}
